﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading;
using Amazon.SQS.Model;
using System.IO;
using System.Net;
using Amazon.S3.Model;
using Amazon.DynamoDB.DocumentModel;
using Amazon.DynamoDB;
using Amazon.DynamoDB.DataModel;

namespace AwsShrinker
{
	class Program
	{
		private const string S3BucketName = "mariommh";

		static void Main(string[] args)
		{
			while (true)
			{
				PrintConsoleMessage("Es wird überprüft, ob Nachrichten vorhanden sind ...", ConsoleColor.Green);

				var msg = RetrieveMessage();

				if (msg.ReceiveMessageResult.Message.Count == 0)
					PrintConsoleMessage("Keine neue Nachricht.", ConsoleColor.White);
				else
				{
					var urlOfFile = GetMessageUrl(msg);
					PrintConsoleMessage("Inhalt der Nachricht: " + urlOfFile, ConsoleColor.Yellow);

					if (urlOfFile != string.Empty)
					{
						var image = GetImageFile(urlOfFile);

						if (image != null)
						{
							PrintConsoleMessage("Bild wird abgerufen.", ConsoleColor.Green);

							var bmp = ConvertToSepia(image);

							if (bmp != null)
							{
								if (StoreImageToS3(bmp))
									PrintConsoleMessage("Datei wurde gespeichert.", ConsoleColor.Green);
								else
									PrintConsoleMessage("Fehler beim Speichern aufgetreten.", ConsoleColor.Red);

								PrintConsoleMessage("Nachricht wird gelöscht.", ConsoleColor.Green);
								DeleteMessage(msg);

								PrintConsoleMessage("Ursprüngliche Datei wird gelöscht.", ConsoleColor.Green);
								DeleteImage(urlOfFile);
							}
							else
								PrintConsoleMessage("Fehler beim Konvertieren des Bildes.", ConsoleColor.Red);
						}
						else
							PrintConsoleMessage("Fehler beim Laden des Bildes.", ConsoleColor.Red);
					}
				}
				  
				Thread.Sleep(1000);
			}
		}

		private static void DeleteImage(string urlOfFile)
		{
			try
			{
				using (var s3Client = Amazon.AWSClientFactory.CreateAmazonS3Client())
				{
					DeleteObjectRequest deleteFile =
						new DeleteObjectRequest()
							.WithBucketName(S3BucketName)
							.WithKey(urlOfFile);

					s3Client.DeleteObject(deleteFile);
				}
			}
			catch (Exception ex)
			{
				PrintConsoleMessage(ex.Message, ConsoleColor.Red);
			}
		}

		private static void DeleteMessage(ReceiveMessageResponse msg)
		{
			try 
			{
				using (var sqsClient = Amazon.AWSClientFactory.CreateAmazonSQSClient(new Amazon.SQS.AmazonSQSConfig().WithServiceURL("http://sqs.eu-west-1.amazonaws.com")))
				{
					DeleteMessageRequest delMsg = new DeleteMessageRequest();
					delMsg.QueueUrl = sqsClient.GetQueueUrl(new GetQueueUrlRequest() { QueueName = "scaleImagesQueue"}).GetQueueUrlResult.QueueUrl;
					delMsg.ReceiptHandle = msg.ReceiveMessageResult.Message.First().ReceiptHandle;
					sqsClient.DeleteMessage(delMsg);
				}
			}
			catch (Exception ex)
			{
				PrintConsoleMessage(ex.Message, ConsoleColor.Red);
			}
		}

		private static bool StoreImageToS3(Bitmap image)
		{
			try
			{
				using (var str = new MemoryStream())
				{
					image.Save(str, System.Drawing.Imaging.ImageFormat.Jpeg);

					using (var s3Client = Amazon.AWSClientFactory.CreateAmazonS3Client())
					{
						var putRequest = new PutObjectRequest();
						putRequest.WithBucketName(S3BucketName)
							.WithKey(Guid.NewGuid().ToString() + ".jpg")
							.WithCannedACL(S3CannedACL.PublicRead)
							.WithInputStream(str);

						using (var sssresponse = s3Client.PutObject(putRequest))
						{
						}

						return true;
					}
				}
			}
			catch (Exception ex)
			{
				PrintConsoleMessage(ex.Message, ConsoleColor.Red);
			}

			return false;
		}

		private static Stream GetImageFile(string urlOfFile)
		{
			try
			{
				WebClient wc = new WebClient();
				var buffer = wc.DownloadData("https://mariommh.s3-eu-west-1.amazonaws.com/" + urlOfFile);

				return new MemoryStream(buffer);
			}
			catch (Exception ex)
			{
				PrintConsoleMessage(ex.Message, ConsoleColor.Red);
			}

			return null;
		}

		private static string GetMessageUrl(ReceiveMessageResponse msg)
		{
			if (msg.IsSetReceiveMessageResult())
			{
				if (msg.ReceiveMessageResult.IsSetMessage())
				{
					if (msg.ReceiveMessageResult.Message.Count == 1)
						return msg.ReceiveMessageResult.Message.First().Body;
				}
			}

			return string.Empty;
		}

		private static ReceiveMessageResponse RetrieveMessage()
		{
			try
			{
				using (var sqsClient = Amazon.AWSClientFactory.CreateAmazonSQSClient(new Amazon.SQS.AmazonSQSConfig().WithServiceURL("http://sqs.eu-west-1.amazonaws.com")))
				{
					var msg = sqsClient.ReceiveMessage(
						new ReceiveMessageRequest()
						{
							QueueUrl = "http://sqs.eu-west-1.amazonaws.com/194459941570/scaleImagesQueue",
							MaxNumberOfMessages = 1
						});

					return msg;
				}
			}
			catch (Exception ex)
			{
				PrintConsoleMessage(ex.Message, ConsoleColor.Red);
			}

			return null;
		}

		public static void PrintConsoleMessage(string text, ConsoleColor color)
		{
			Console.ForegroundColor = color;
			Console.WriteLine(text);
		}

		public static Bitmap ConvertToSepia(Stream img)
		{
			try
			{
				Bitmap bmp = new Bitmap(img);
				int A, R, G, B;
				Color pixelColor;
				int depth = 15;

				for (int i = 0; i < bmp.Height; i++)
				{
					for (int j = 0; j < bmp.Width; j++)
					{
						pixelColor = bmp.GetPixel(j, i);
						A = pixelColor.A;
						R = (int)((0.299 * pixelColor.R) + (0.587 * pixelColor.G) + (0.114 * pixelColor.B));
						G = B = R;

						R += (depth * 2);
						if (R > 255)
						{
							R = 255;
						}
						G += depth;
						if (G > 255)
						{
							G = 255;
						}

						bmp.SetPixel(j, i, Color.FromArgb(A, R, G, B));
					}
				}

				return bmp;
			}
			catch (Exception ex)
			{
				PrintConsoleMessage(ex.Message, ConsoleColor.Red);
			}

			return null;
		}

		public static void TestStuff(AmazonDynamoDB client)
		{
			Table dataTable = Table.LoadTable(client, "Artikel");

			Document item = new Document();
			item["Name"] = "Mario Meir-Huber";
			item["Id"] = 2;
			item["EMail"] = "mario@meirhuber.de";
			item["Eltern"] = new List<string> { "Margit", "Hans" };
			item["Geboren"] = new DateTime(1984, 3, 1);
			item["Twitter"] = "mario_mh";
			dataTable.PutItem(item);

			DynamoDBContext context = new DynamoDBContext(client);

			var obj = new Movie() { Name = "AWS Lernen", ReleaseDate = DateTime.Now };

			context.Save<Movie>(obj);
		}

	}
}
